
#include "UFLLight.h"
#include <stdio.h>

using namespace ufl;

// class -- UFLBaseLightModel

// 光源唯一ID生成变量
ufl_uint64 UFLBaseLightModel::_unique_id = 0;

UFLBaseLightModel::UFLBaseLightModel()
:_ambient(ufl_color_4f(0.0f)), _diffuse(ufl_color_4f(0.0f)), _specular(ufl_color_4f(0.0f)),
_state(true), _id(UFLBaseLightModel::_genLightID()), _debugModel(false)
{

}

UFLBaseLightModel::~UFLBaseLightModel()
{

}

ufl_uint64 UFLBaseLightModel::_genLightID()
{
	return ++_unique_id;
}

bool UFLBaseLightModel::intoGPU(UFLShaderProgram& shader)
{
	if (shader.getProgramID() > 0)
	{
		ufl_string uniformName;

		// 环境光
        uniformName = _name + ".baseAttr.ambient";
		shader.setUniform(uniformName, _ambient);

		// 漫射光
        uniformName = _name + ".baseAttr.diffuse";
		shader.setUniform(uniformName, _diffuse);

		// 镜面高光
        uniformName = _name + ".baseAttr.specular";
		shader.setUniform(uniformName, _specular);

		// 光源状态
        uniformName = _name + ".baseAttr.state";
		shader.setUniform(uniformName, _state);
	}
	else
	{
		fprintf(stderr, "Don't attach to a valid shader program.");
		return false;
	}

	return true;
}

void UFLBaseLightModel::debugDraw()
{
	if (_debugModel)
	{
		_debugShader.use();
	}
}

// class -- UFLDirectionLightModel
UFLDirectionLightModel::UFLDirectionLightModel()
:UFLBaseLightModel(), _diretion(ufl_vertex_4f(0.0f))
{
	_name = "dirLight";
}

UFLDirectionLightModel::~UFLDirectionLightModel()
{

}

bool UFLDirectionLightModel::intoGPU(UFLShaderProgram& shader)
{
	if (UFLBaseLightModel::intoGPU(shader))
	{
        ufl_string uniformName;
        
		// 光照方向
        uniformName = _name + ".dir";
		shader.setUniform(uniformName, _diretion);
	}
	else
	{
		return false;
	}

	return true;
}

// class -- UFLPointLightModel
UFLPointLightModel::UFLPointLightModel()
:UFLBaseLightModel(), _position(ufl_vertex_3f(0.0f)), _atten(ufl_vertex_3f(0.0f)), _range(0.0f)
{
	_name = "pointLight";
}

UFLPointLightModel::~UFLPointLightModel()
{

}

bool UFLPointLightModel::intoGPU(UFLShaderProgram& shader)
{
	if (UFLBaseLightModel::intoGPU(shader))
	{
		ufl_string uniformName;

		// 光源位置
        uniformName = _name + ".position";
		shader.setUniform(uniformName, _position);

		// 光照范围
        uniformName = _name + ".range";
		shader.setUniform(uniformName, _range);

		// 距离衰减系数
        uniformName = _name + ".atten";
		shader.setUniform(uniformName, _atten);
	}
	else
	{
		return false;
	}

	return true;
}

// class -- UFLSpotLightModel
UFLSpotLightModel::UFLSpotLightModel()
:UFLBaseLightModel()
{

}

UFLSpotLightModel::~UFLSpotLightModel()
{

}

ufl_boolean UFLSpotLightModel::intoGPU(UFLShaderProgram& shader)
{
	if (UFLBaseLightModel::intoGPU(shader))
	{
		ufl_string uniformName;

		// 截断角度
        uniformName = _name + ".cutoff";
		shader.setUniform(uniformName, _cutoff);

		//
        uniformName = _name + ".pf";
		shader.setUniform(uniformName, _pf);

		// 距离衰减系数
        uniformName = _name + ".atten";
		shader.setUniform(uniformName, _atten);

		// 光照方向
        uniformName = _name + ".dir";
		shader.setUniform(uniformName, _dir);

		// 光源位置
        uniformName = _name + ".position";
		shader.setUniform(uniformName, _position);
	}
	else
	{
		return false;
	}

	return true;
}